package ru.stork.vasilisa.model

import ru.stork.vasilisa.exceptions.VasilisaModelException
import ru.stork.vasilisa.lang

import com.wordpress.michid.Memoize._
import com.yelbota.util.Lazy

sealed trait Type extends NotNull

case class Parameter(name: String, node: lang.Node)
  extends Type

case class Declaration(t: Lazy[VasilisaType], typeParameters: Option[List[Type]], node: lang.Node) extends Type {
  def validate() {
    // check, type params count in declaration equals
    // params count in parametrized trait.
    typeParameters match {
      case Some(x) =>
        if (t.get.typeParameters.size != x.size)
          throw new VasilisaModelException(node, VasilisaModelException.ERR_INVALID_TYPE_PARAM_CNT);
      case None =>
        if (t.get.typeParameters.size > 0)
          throw new VasilisaModelException(node, VasilisaModelException.ERR_INVALID_TYPE_PARAM_CNT);
    }
  }
}

object Declaration {

  private def _fromNode(ns: Namespace, node: lang.TypeDeclaration): Declaration =
    Declaration(
      ns.findTrait(node.name) match {
        case Some(x) => x
        case None => throw new VasilisaModelException(
          node, VasilisaModelException.ERR_TRAIT_NOT_FOUND)
      },
      node.typeParameters match {
        case Some(x) => Some( x map ( td => fromNode(ns, td) ) )
        case None => None
      },
      node
    )

  val fromNode = memoize(_fromNode _)
}
